#include "Init.h"

std::optional<std::string> parse_git_url_to_string(const std::string &url)
{
    // 正则表达式匹配SSH格式的Git URL (git@host:user/repo.git)
    std::regex ssh_re(R"(git@([^:]+):([^/]+)/([^/]+?)(\.git)?$)");
    // 正则表达式匹配HTTPS格式的Git URL (https://host/user/repo.git)
    std::regex https_re(R"(https?://([^/]+)/([^/]+)/([^/]+?)(\.git)?$)");
    // 正则表达式匹配HTTPS格式的Git URL (https://host:port/user/repo.git)
    std::regex https_port_re(R"(https?://([^/:]+):\d+/([^/]+)/([^/]+?)(\.git)?$)");

    std::smatch match;

    if (std::regex_match(url, match, ssh_re))
    {
        // SSH格式: git@host:user/repo.git
        return match[2].str() + "/" + match[3].str();
    }
    else if (std::regex_match(url, match, https_re))
    {
        // HTTPS格式: https://host/user/repo.git
        return match[2].str() + "/" + match[3].str();
    }
    else if (std::regex_match(url, match, https_port_re))
    {
        // HTTPS带端口格式: https://host:port/user/repo.git
        return match[2].str() + "/" + match[3].str();
    }

    return std::nullopt;
}

/**
 * @brief 从 Git 配置文件中提取远程 URL
 *
 * @param config_path .git/config 文件路径
 * @return std::optional<std::string> 解析出的 URL，失败返回 std::nullopt
 */
std::optional<std::string> parse_git_config_url(const std::filesystem::path &config_path)
{
    std::ifstream config_file(config_path);
    if (!config_file.is_open())
    {
        std::cerr << "Error: Failed to open Git config file: " << config_path << std::endl;
        return std::nullopt;
    }

    std::regex url_regex(R"(url\s*=\s*(.+))");
    std::string line;
    bool in_remote_section = false;

    while (std::getline(config_file, line))
    {
        // 检查是否进入 [remote "origin"] 部分
        if (line.find("[remote \"origin\"]") != std::string::npos)
        {
            in_remote_section = true;
            continue;
        }

        // 如果在远程部分且找到 URL
        if (in_remote_section)
        {
            std::smatch match;
            if (std::regex_search(line, match, url_regex))
            {
                return match[1].str();
            }
        }

        // 如果遇到新的节，退出远程部分
        if (line.find('[') != std::string::npos && in_remote_section)
        {
            break;
        }
    }

    return std::nullopt;
}

/**
 * @brief 从 .git/config 文件获取远程 URL
 *
 * @param dir 要查找的目录路径
 * @return std::string 远程 URL，失败返回空字符串
 */
std::string get_url(const std::filesystem::path &dir)
{
    // 获取 .git 目录路径 (dir父级的父级)
    std::filesystem::path git_dir = dir.parent_path().parent_path() / ".git";

    // 检查是否是普通文件（可能是 gitdir 引用）
    if (std::filesystem::is_regular_file(git_dir))
    {
        std::ifstream gitdir_file(git_dir);
        std::string actual_git_path;
        if (std::getline(gitdir_file, actual_git_path))
        {
            if (actual_git_path.find("gitdir: ") == 0)
            {
                git_dir = std::filesystem::path(actual_git_path.substr(8));
            }
        }
    }

    // 构建 config 文件路径
    std::filesystem::path config_path = git_dir / "config";

    if (!std::filesystem::exists(config_path))
    {
        if (std::filesystem::is_directory(config_path.parent_path()))
        {
            std::cerr << "Error: Git config file not found in: " << config_path << std::endl;
        }
        else
        {
            std::cerr << "Error: Git directory not found: " << config_path.parent_path() << std::endl;
        }
        return "";
    }

    auto url = parse_git_config_url(config_path);
    return url ? *url : "";
}


bool write_to_cast_lib(const std::string &content,
                       const std::filesystem::path &lab_dir,
                       const std::filesystem::path &dir)
{
    const std::string &mode = "w";
    // 1. 检查/创建目录
    try
    {
        if (!std::filesystem::exists(dir))
        {
            std::filesystem::create_directories(dir); // 递归创建目录
            std::cout << "Created directory: " << dir << std::endl;
        }
    }
    catch (const std::filesystem::filesystem_error &e)
    {
        std::cerr << "Directory error: " << e.what() << std::endl;
        return false;
    }

    std::string url = get_url(lab_dir);
    std::string file_name = lab_dir.stem().string();
    std::string file_dir = *parse_git_url_to_string(url);
    std::filesystem::path r_dir= dir / file_dir;
    std::error_code ec;
    std::filesystem::create_directories(r_dir),ec;
    if (ec){
        std::cerr << "创建目录失败: " << ec.message() << std::endl;
    }
    std::filesystem::path r_file_name = r_dir.string()+"/"+file_name+"_cast.txt";
    //  打开文件
    std::ios_base::openmode filemode = std::ios::out;
    if (mode == "a")
    {
        filemode |= std::ios::app; // 追加模式
    }
    else
    {
        filemode |= std::ios::trunc; // 覆盖模式（默认）
    }

    std::ofstream out_file(r_file_name, filemode);
    if (!out_file)
    {
        std::cerr << "Failed to open file: " << r_file_name << std::endl;
        return false;
    }

    //  写入内容
    out_file << content;

    return true;
}



// 获取目录及子目录下所有.cast文件的路径（返回std::filesystem::path向量）
std::vector<std::filesystem::path> get_cast_file(const std::filesystem::path &directory)
{
    std::vector<std::filesystem::path> files;

    if (!std::filesystem::exists(directory))
    {
        std::cerr << "Directory does not exist: " << directory << std::endl;
        return files;
    }

    if (!std::filesystem::is_directory(directory))
    {
        std::cerr << "Path is not a directory: " << directory << std::endl;
        return files;
    }

    // 使用递归目录迭代器遍历所有子目录
    for (const auto &entry : std::filesystem::recursive_directory_iterator(directory))
    {
        if (entry.is_regular_file() && entry.path().extension() == ".cast")
        {
            files.push_back(entry.path());
        }
    }

    return files;
}

void init(const std::filesystem::path &file_dir, const std::filesystem::path &cast_dir)
{
    std::vector<std::filesystem::path> cast_file = get_cast_file(file_dir);
    std::cout << "Found " << cast_file.size() << " files to process" << std::endl;
    for (auto &t : cast_file) // 直接遍历容器，不需要显式调用 begin()/end()
    {
        std::string str;
        std::vector<std::string> cast_str = process_cast_file_init(t);
        records_join(cast_str, str);
        write_to_cast_lib(str, t, cast_dir);
    }
}